/******************************************************************************
 * Author:      671643387
 * Created:     2016/9/26
 *****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
//>> 导入库
require('./global.js');
var logger              = require('./logger.js');
var server              = require('./server.js');
global.config           = require(require('fs').existsSync('../config.js') ? '../config.js' : './config.js');
var logic               = require('./logic');
global.ErrorCodes       = require('./logic/error.js').ErrorCodes;
global.findErrString    = require('./logic/error.js').findString;
var LaomaziDoTick       = require('./logic/laomazi.js').doTick;

///////////////////////////////////////////////////////////////////////////////
//>> 全局变量
global.gDBPlat = null;
global.gDBUser = null;

///////////////////////////////////////////////////////////////////////////////
//>> 程序入口
function main(){
    // 初始化日志
    logger.init();

    // 连接数据库
    server.loadDB(function(db){
        LOG('MongoDB connected');

        global.gDBPlat = db.collection('plat');
        global.gDBUser = db.collection('user');

        var PlayerManager = require('./logic/player.js').PlayerManger;
        global.gPlayerMgr = new PlayerManager();

        // 启动WebSocket服务器
        startWssServer();

        // 定时任务
        setInterval(function(){
            LaomaziDoTick();
        }, 300000);
    });
}
main();

///////////////////////////////////////////////////////////////////////////////
//>> 变量
global.gConnMap = {};   // 连接表
global.gConnIdGen = 0;  // 连接编号

///////////////////////////////////////////////////////////////////////////////
//>> 功能函数

/**
 * 启动WSS服务器
 */
function startWssServer() {
    server.startWssServer('game', config.GamePort, config.GameHost, function(query, res, resp){
        do {
            resp.code = 1;
            
            var uid = +query.uid;
            if (isNaN(uid)) {
                resp.desc = 'no uid';
                break;
            }

            if (!query.mod) {
                resp.desc = 'no mod'; break;
            } else if (!query.act) {
                resp.desc = 'no act'; break;
            } else if (!query.args) {
                resp.desc = 'no args'; break;
            } else if (typeof query.args != 'object' && query.act != "addPlayerCard"){
                resp.desc = 'args not in json format'; break;
            }

            resp.code = 0;

            var logicHandler = null;
            var module = logic[query.mod];

            if (module) {
                logicHandler = module[query.act];
            }

            if (!logicHandler) {
                resp.code = 1;
                resp.desc = 'act ' + query.act + ' not support in mod ' + query.mod;
                break;
            }
            var wx_name = query.args.name ? query.args.name : null;
            gPlayerMgr.get(uid, wx_name, function(player){
                if (!player) {
                    resp.code = 1;
                    resp.desc = 'get player failed err';
                    onReqHandled(res, resp);
                } else {
                    handleGameReq(player, query, res, resp);
                }
            });
            return;
        } while(false);

        onReqHandled(res, resp);
    }, function(wssServer){
        wssServer.on('request', function(request) {
            checkOriginIsAllowed(request.origin, function(checkPassed){
                if (!checkPassed) {
                    request.reject();
                    LOG('REJECT: ' + request.origin);
                    return;
                }

                var conn = request.accept('default-protocol', request.origin);
                LOG(Date.getStamp() + ' Connection accepted.');

                conn.conn_id = ++gConnIdGen;
                gConnMap[conn.conn_id] = conn;
                conn.on('message', function(message) {
                    if (message.type === 'utf8') {
                        conn._time = Date.getStamp();
                        var query = null;
                        try {
                            query = JSON.parse(message.utf8Data);
                        } catch(error) {
                            ERROR('wss message ' + message.utf8Data);
                            query = {};
                        }
                        if (typeof(query) != 'object') {
                            //ERROR('message not a object');
                            return;
                        }

                        if (!query.args) {
                            query.args = {};
                        }

                        query.conn = conn;
                        handleWsQuery(query, function(resp, state) {
                            //onWsHandled(query, resp);
                            if (state) {
                                if (state == 'close') {
                                    // 握手失败，断开连接
                                    conn.close();
                                }
                            }
                        });
                    }
                });
                conn.on('close', function() {
                    handleConnectionClose(conn, request.origin);
                });
            });
        });
    }, function(callback){
        // 服务器退出处理
        callback && callback();
    });
}



/**
 * 处理请求
 * @param query
 * @param handler
 */
function handleWsQuery(query, handler) {
    var resp = {
        'code': 1,
        'desc': '',
        'mod':  query.mod,
        'act':  query.act,
        'data': {}
    };

    do {
        var uid = +query.uid;
        if (isNaN(uid)) {
            resp.desc = 'no uid'; break;
        }

        if (!query.mod) {
            resp.desc = 'no mod'; break;
        } else if (!query.act) {
            resp.desc = 'no act'; break;
        } else if (!query.args) {
            resp.desc = 'no args'; break;
        } else if (typeof query.args != 'object'){
            resp.desc = 'args not in json format'; break;
        }
        resp.code = 0;

        var wsHandler = null;
        var module = logic[query.mod];
        if (module) {
            wsHandler = module[query.act];
        }

        if (!wsHandler) {
            resp.code = 1;
            resp.desc = 'act ' + query.act + ' not support in mod ' + query.mod;
            break;
        }

        var wx_name = query.args.name ? query.args.name : null;
        gPlayerMgr.get(uid, wx_name, function(player){
            if (player) {
                player.setConn(query.conn);
                wsHandler(player, query, resp, function(arg) {
                    handler(resp, arg);
                });
            } else {
                resp.code = 1;
                resp.desc = 'get player failed';
                handler(resp);
            }
        });
        return;
    }while(false);

    handler(resp);
}

function handleGameReq(player, query, res, resp) {
    LOG('PROCESSING ' + query.mod + '.' + query.act);

    var logicHandler = logic[query.mod][query.act];
    logicHandler(player, query, resp, function() {
        onReqHandled(res, resp);
    });
}